package com.mallcai.bigdata.ladon.tools.dingtalk;

import com.alibaba.fastjson.JSONObject;
import com.mallcai.bigdata.ladon.tools.FileUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

/**
 * described :
 * Created by CaKeDou on 2019-08-20 14:32.
 * Modify:
 */
public class DingTalkUtil {

    private static HttpClient httpClient = HttpClients.createDefault();

    /**
     * 发送钉钉文本消息
     *
     * @param webhook String 钉钉机器人地址
     * @param message 消息内容
     */
    public static SendResult send(String webhook, Message message) {
        SendResult sendResult = new SendResult();
        try {
            HttpPost httpPost = new HttpPost(webhook);
            httpPost.addHeader("Content-Type", "application/json; charset=utf-8");
            StringEntity se = new StringEntity(message.toJsonString(), "utf-8");
            httpPost.setEntity(se);

            HttpResponse response = httpClient.execute(httpPost);
            if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                String result = EntityUtils.toString(response.getEntity());
                JSONObject obj = JSONObject.parseObject(result);

                Integer errorCode = obj.getInteger("errcode");
                sendResult.setErrorCode(errorCode);
                sendResult.setErrorMsg(obj.getString("errmsg"));
                sendResult.setSuccess(errorCode.equals(0));
            }
        } catch (Throwable e) {
            sendResult.setErrorCode(-1);
            sendResult.setErrorMsg("IO异常");
        }
        return sendResult;
    }

    /**
     * 发送钉钉文本消息
     *
     * @param webhook String 钉钉机器人地址
     * @param message 消息内容
     */
    public static SendResult send(String webhook, String message) {
        return send(webhook, new Message(message));
    }

    /**
     * 最大检查行数
     */
    private static int MAX_CHECK_LINE = 10000;

    /**
     * @param filePath    被检查文件的路径
     * @param startLine   开始检查的行数,第一次时需要传入文件末尾的行
     * @param alarmNumber 告警的阀值
     * @param webHook     钉钉机器人地址
     * @param message     发送的消息内容
     * @return 检查完之后文件的行数
     */
    public static int checkError(String filePath, int startLine, int alarmNumber, String webHook, String message) {
        int endLine = FileUtil.getFileLines(filePath);
        int checkLine = endLine;
        //防止一次性读入到内存的行数过多,做最大限制
        if (endLine - startLine > MAX_CHECK_LINE) {
            checkLine = startLine + MAX_CHECK_LINE;
        }
        List<String> lines = FileUtil.readFile2List(filePath, startLine, checkLine, "utf-8");
        if (lines == null) {
            return endLine;
        }
        List<String> errorLines = lines.stream().filter(oneLine -> StringUtils.containsIgnoreCase(oneLine, "error") || StringUtils.contains(oneLine, "Exception")).collect(Collectors.toList());

        if (errorLines.size() >= alarmNumber) {
            //过滤重复的错误内容并发送
            HashSet<String> containsInfo = new HashSet<>();
            String errorContext = errorLines.stream().filter(oneLine -> {
                String lastTwentyChar = StringUtils.right(oneLine, 20);
                if (!containsInfo.contains(lastTwentyChar)) {
                    containsInfo.add(lastTwentyChar);
                    return true;
                }
                return false;
            }).collect(Collectors.joining("\n"));
            DingTalkUtil.send(webHook, message + "\n" + errorContext);
        }
        return endLine;
    }

    /**
     * 此方法需要定时任务调用,每次开始检查的行数为上次检查的
     *
     * @param filePath  被检查文件的路径
     * @param startLine 开始检查的行数,第一次时需要传入文件末尾的行
     * @param webHook   钉钉机器人地址
     * @param appName   应用的名称
     * @return 检查完之后文件的行数
     */
    public static int checkError(String filePath, int startLine, String webHook, String appName) {
        return checkError(filePath, startLine, 40, webHook, "最近一段时间[" + appName + "]发生错误的个数已超过20,请注意,错误内容如下:");
    }
}
